#include "SocketTcp.h"

CSocketTcp::CSocketTcp(void)
{
}

CSocketTcp::~CSocketTcp(void)
{
}

bool CSocketTcp::CreateSocket(void)
{
	m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (m_hSocket == INVALID_SOCKET)
		return false;

	int optval = 1;

#ifdef WIN32
	if ( setsockopt( m_hSocket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &optval, sizeof( int ) ) != 0 ) 
#endif
	{
		Close();
		return false;
	}

	//int enable = 1;
	//setsockopt(m_hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable));

	return true;
}

bool CSocketTcp::Bind(unsigned short usPort)
{
	if (m_hSocket == INVALID_SOCKET)
		return false;

	struct sockaddr_in svrAddr;
	svrAddr.sin_addr.s_addr = htonl(INADDR_ANY); 	
	svrAddr.sin_family = AF_INET;
	svrAddr.sin_port = htons(usPort);

	if (bind(m_hSocket, (struct sockaddr *)&svrAddr,sizeof(svrAddr)) == -1)
	{
		Close();
		return false;
	}

	return true;
}

bool CSocketTcp::Listen(unsigned short usNum/* = 20*/)
{
	if (m_hSocket == INVALID_SOCKET)
		return false;

	if (listen(m_hSocket, usNum) == -1)
	{
		Close();
		return false;
	}

	return true;
}

int CSocketTcp::Connect(const char *szIP, unsigned short usPort)
{
	if (m_hSocket == INVALID_SOCKET)
		return false;

	struct sockaddr_in remoteAddr;
	remoteAddr.sin_addr.s_addr = inet_addr(szIP); 	
	remoteAddr.sin_family = AF_INET;
	remoteAddr.sin_port = htons(usPort);

	return connect(m_hSocket,(struct sockaddr*)&remoteAddr,sizeof(remoteAddr));
}

SOCKET CSocketTcp::Accept(void)
{
#ifdef _WIN32
	int nLen;
#endif

	int nConn = 0;
	struct sockaddr_in from_addr;
	nLen = sizeof(from_addr);

	nConn = accept(m_hSocket, (struct sockaddr *)&from_addr, &nLen);
	if (nConn < 0)		
		return 0;

	return nConn;
}

int CSocketTcp::RecvData(SOCKET nSocket,char *szBuf, int nLen)
{
	int rlen;
	rlen = recv(nSocket, szBuf , nLen , 0);
	if( rlen == 0 ) 
		return -1;
	else if ( rlen < 0 ) 
	{	
		int err_code;
#ifdef WIN32
		err_code = WSAGetLastError();
		if( err_code == WSAEWOULDBLOCK || err_code == ERROR_SUCCESS) {
#endif
			rlen=0;
		}
	}
	return rlen;
}

int CSocketTcp::ReadDataEx(SOCKET nSocket, char *pBuff, int nBuffLen)
{
	int nRet = 0;
	int nReadNum = 0;

	while ((nRet = recv(nSocket,pBuff+nReadNum,nBuffLen-1,0)) > 0)
	{
		nReadNum += nRet;
	}

	if (nRet == -1)
	{
		int err_code;
#ifdef _WIN32
		err_code = WSAGetLastError();
		if( err_code == WSAEWOULDBLOCK || err_code == ERROR_SUCCESS) {
#endif
			return nReadNum;			
		}

		return -1;
	}
	else if(nRet == 0)
	{
		return -1;
	}

	return nReadNum;
}

int CSocketTcp::RecvData(char *pBuff, int nLen)
{
	return RecvData(m_hSocket,pBuff,nLen);
}

int CSocketTcp::SendData(SOCKET nSocket, const char *pData, int nLen)
{
	int nRet = 0;
	nRet=send(nSocket,pData,nLen,0);
	if (nRet < 0)
	{
#ifdef _WIN32
		DWORD dwError = WSAGetLastError();
		if (dwError == WSAEWOULDBLOCK || dwError == ERROR_SUCCESS)
			return 0;
		else
			return nRet;	
#endif
	}
	
	return nRet;
}

int CSocketTcp::SendData(const char *pData, int nLen)
{
	return SendData(m_hSocket,pData,nLen);
}
